package main

import (
	"fmt"
	"io"
	"net"
	"strings"
	"time"
)

type User struct {
	Name string
	Addr string
	C    chan string
	conn net.Conn

	server *Server
	isLive chan bool
}

// 用户消息监听
func (user *User) MessageListener() {
	// 从消息管道中读取消息，并写回到客户端
	for {
		msg := <-user.C

		user.conn.Write([]byte(msg))
	}
}

func (user *User) ReadListener() {
	// 监听用户的消息
	for {
		// 创建缓冲区
		buf := make([]byte, 4096)

		// socket中读取字节流，阻塞
		n, err := user.conn.Read(buf)

		if n == 0 { // 用户断开连接
			user.Offline()
			return
		}

		if err != nil && err != io.EOF {
			fmt.Println("Read Client message err: ", err)
			return
		}

		// 向管道中发送活动状态
		user.isLive <- true

		message := string(buf[:n-1])

		// 收到消息后的用户处理
		user.DoMessage(message)
	}
}

func (user *User) IsLiveListener() {
	for {
		select {
		case <-user.isLive: // 不断检测是否活动

		case <-time.After(5 * time.Minute): // 不活动会触发这个条件，一旦超时就会被踢出
			user.SendMessage("[system] 超时未发言, 您已被踢出聊天室！\n")
			// 销毁可用资源
			close(user.C)
			close(user.isLive)

			// 断开连接
			user.conn.Close()
		}
	}
}

func NewUser(conn net.Conn, server *Server) *User {
	// 创建用户
	user := &User{
		Name: conn.RemoteAddr().String(),
		Addr: conn.RemoteAddr().String(),
		C:    make(chan string),
		conn: conn,

		server: server,
		isLive: make(chan bool),
	}

	// 启用用户消息监听器
	go user.MessageListener()

	return user
}

func (user *User) Online() {
	// 用户上线
	user.server.BroadCast(user, "online.")
}

func (user *User) Offline() {
	// 将用户从用户列表中去除
	user.server.UserMapLock.Lock()
	delete(user.server.UserMap, user.Name)
	user.server.UserMapLock.Unlock()

	// 发送广播
	user.server.BroadCast(user, "offline.")
}

func (user *User) SendMessage(message string) {
	user.conn.Write([]byte(message))
}

func (user *User) SendMessageToUser(toUser *User, message string) {
	msg := fmt.Sprintf("[Receive Message from: %s] : %s\n", user.Name, message)
	toUser.conn.Write([]byte(msg))
}

func (user *User) Disconnect() {
	user.Offline()
	user.conn.Close()
}

func (user *User) DoMessage(message string) {

	if len(message) == 0 {
		return
	}

	if message == "who" {
		user.server.UserMapLock.Lock()
		for _, cli := range user.server.UserMap {
			msg := fmt.Sprintf("[%s]%s:%s\n", cli.Addr, cli.Name, "用户在线")
			user.SendMessage(msg)
		}
		user.server.UserMapLock.Unlock()
		return
	} else if message == "exit" {
		user.Disconnect()
	} else if len(message) > 7 && message[:7] == "rename|" { // rename|NewName
		newName := strings.Split(message, "|")[1]

		if newName != user.Name {
			nameExists := false

			user.server.UserMapLock.Lock()
			// 检查用户是否存在
			if user.server.UserMap[newName] == nil {
				// 移除用户
				delete(user.server.UserMap, user.Name)

				// 添加用户
				user.server.UserMap[newName] = user
			} else {
				nameExists = true
			}
			user.server.UserMapLock.Unlock()

			if nameExists {
				user.SendMessage(fmt.Sprintf("[system] rename failed ! user name %s always exists.\n", newName))
			} else {
				user.Name = newName
				user.SendMessage("[system] rename success !\n")
			}
		} else {
			user.SendMessage(fmt.Sprintf("[system] user name %s equaled to old name\n", newName))
		}
		return
	} else if len(message) > 3 && message[:3] == "to|" {
		parts := strings.Split(message[3:], "|")

		if len(parts) == 2 { // [name, msg]
			// 用户存在
			if user.server.UserMap[parts[0]] != nil {
				user.SendMessageToUser(user.server.UserMap[parts[0]], parts[1])
			} else {
				user.SendMessage(fmt.Sprintf("[system] target user %s not exists or always offline !\n", parts[0]))
			}

			return
		}
	}
	// 当接收到用户发送来的信息时
	user.server.BroadCast(user, message)
}
